//
//  NcitBleDevice.m
//  BleHrateDemo
//
//  Created by Yongfeng Li on 8/15/14.
//  Copyright (c) 2014 Yongfeng Li. All rights reserved.
//

#import "NcitBleDevice.h"

#define _KgcovLb 2.20462262

#import "AppDelegate.h"

//huitaike
#import "HandBlueIdea.h"
#import "HandBlueValue.h"
//huitaike


//static char _IP_ADDR_Deubg[32] = "192.168.1.188";
//static char _IP_ADDR_Deubg[32] = "192.168.0.205";

//HW
static NSString * const hrsServiceUUIDString = @"0000180D-0000-1000-8000-00805F9B34FB";
static NSString * const hrsHeartRateCharacteristicUUIDString = @"00002A37-0000-1000-8000-00805F9B34FB";
static NSString * const hrsSensorLocationCharacteristicUUIDString = @"00002A38-0000-1000-8000-00805F9B34FB";

static NSString * const batteryServiceUUIDString = @"0000180F-0000-1000-8000-00805F9B34FB";
static NSString * const batteryLevelCharacteristicUUIDString = @"00002A19-0000-1000-8000-00805F9B34FB";

//static NSInteger _nHrateTimeVal = 0;


@implementation NcitBleDevice {
  //hui tai ke
  NSMutableArray   *m_characteristicsArray;
  //hui tai ke
  
  BOOL _bNeedMatched;
  
  BOOL _bJustScanDev;
  BOOL _bStopMeas;
  BOOL _bReConnPedo;
    
  BOOL _bIsSuptBLe;
  BOOL _bAutoConnect;
  BOOL _bRcvBLeData;
  BOOL _bConnBleDev;
    
  BOOL _bLoadSavedBleDev;
  NSString* _sBleUuid;
  NSString* _sBlePerName;
  NSString* _sConnBleName;
    
  id _bleDelegate;
    
  //short _nDevType;
  NSString* _sCurtSelUuid;
  //NSString* _sStoredHMUuid;
  //NSString* _sStoredPEUuid;
    
  CBCentralManager*   _bleMgr;
  CBPeripheral*       _pBleDevPer;
  
  CBService* _pHrateService;
  CBService* _pPedoService;

  
    //CBPeripheral*       _pBleSyncSvr;
  CBCharacteristic*   _pBleDevChar;
  CBCharacteristic*   _pBlePedoChar;

  CBCharacteristic*   _pBleMhrChar;
  CBCharacteristic*   _pBleSyncChar;
  CBCharacteristic*   _pBleBatLvlChar;
  
  CBCharacteristic*   _pYunmaiChar;
  
  NSMutableArray*     hrConntMonitors;
    
    NSArray* _arSelBleDev;
    NSTimer* _measTimer;
    
    BOOL _bWriteBraceletVal;
    NSDateFormatter* _dtFormat;
    
    BOOL _bBodyMale;
    short _nBodyYear;
    float _fBodyHgt;
    //NSString* _rcvData;
    BOOL _bSyncDevData;
    
    Byte _nDevTypeIdx;
  
  BOOL _bConnYunmai;
  BOOL _bConnNuyu;
  
  //bebug
  BOOL _bConnSocketSvr;
  NSUInteger _nDebugDataType;
  BOOL _bSecondSync;
  
  dispatch_queue_t _centralQueue;
  BOOL _bBatteryNotify;
  BOOL _bSyncDevCharFound;
  
  BOOL _bHrateDev;
  BOOL _bAlreadySnedHrmData;
  
  //HW
  CBUUID *HR_Service_UUID;
  CBUUID *HR_Measurement_Characteristic_UUID;
  CBUUID *HR_Location_Characteristic_UUID;
  CBUUID *Battery_Service_UUID;
  CBUUID *Battery_Level_Characteristic_UUID;
  //CBUUID *dfuService_UUID;
  //CBUUID *dfuControl_Point_Characteristic_UUID;
  //CBUUID *dfuPacket_Characteristic_UUID;
  
  //huitaike
  HandBlueIdea* m_handIdea;
  NSMutableDictionary* m_heartRateDic;
  NSMutableArray* m_heartRateArray;
  
  int checkLeiJiNum;
  //huitaike
}

@synthesize  m_pBleDevPer = _pBleDevPer;

/*****************************/
/*    ble strap gague   */
/*****************************/

#pragma mark - BLE init
- (id) initBleDevice
{
  //hui tai ke
  m_characteristicsArray = [[NSMutableArray alloc] init];
  //hui tai ke
  
  _bNeedMatched = NO;
  
  _bJustScanDev = NO;
  _bStopMeas = NO;
  _bReConnPedo = NO;
    
    _bIsSuptBLe = NO;
    _bAutoConnect = YES;
    _bRcvBLeData = NO;
    _bConnBleDev = NO;
    _bLoadSavedBleDev = NO;
    //BLE ini
    hrConntMonitors = [[NSMutableArray alloc] init];
  
  //_centralQueue = dispatch_queue_create("centrql", DISPATCH_QUEUE_SERIAL);
  //_bleMgr = [[CBCentralManager alloc] initWithDelegate:self queue:_centralQueue];
  
  _bleMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
  //_bleMgr.delegate = self;
    
  _pBleDevPer = nil;
  _pHrateService = nil;
  _pPedoService = nil;
  //_pBleSyncSvr = nil;
 
  _pBleDevChar = nil;
  _pBlePedoChar = nil;
  _pBleMhrChar = nil;
  _pBleSyncChar = nil;
  _pBleBatLvlChar = nil;
  
  _pYunmaiChar = nil;
  
  _arSelBleDev = nil;
  _measTimer = nil;
    
    _dtFormat = [[NSDateFormatter alloc] init];
    //_rcvData = [NSString alloc].init;
    
    _bWriteBraceletVal = NO;
    
    _bBodyMale = NO;
    _nBodyYear = -1;
    _fBodyHgt = 0.0;
    
    _sCurtSelUuid = @"";
    _sBlePerName = @"";
    _sConnBleName = nil;
    
    _bSyncDevData = NO;
    _nDevTypeIdx = 255;
  
  //debug
  /*AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  [pApp CloseScaleHost];
  [pApp ConnScaleHost:YES IpAddr:_IP_ADDR_Deubg];*/
  //debug
  _bConnSocketSvr = YES;
  _nDebugDataType = 3;
  _bSecondSync = NO;
  
  _bConnYunmai = NO;
  _bConnNuyu = NO;
  
  _bBatteryNotify = NO;
  _bSyncDevCharFound = NO;
  
  _bHrateDev = NO;
  _bAlreadySnedHrmData = NO;
  
  //HW
  HR_Service_UUID = [CBUUID UUIDWithString:hrsServiceUUIDString];
  HR_Measurement_Characteristic_UUID = [CBUUID UUIDWithString:hrsHeartRateCharacteristicUUIDString];
  HR_Location_Characteristic_UUID = [CBUUID UUIDWithString:hrsSensorLocationCharacteristicUUIDString];
  Battery_Service_UUID = [CBUUID UUIDWithString:batteryServiceUUIDString];
  Battery_Level_Characteristic_UUID = [CBUUID UUIDWithString:batteryLevelCharacteristicUUIDString];
  
  
  //huitaike
  m_handIdea = [[HandBlueIdea alloc] init];
  m_heartRateDic = [[NSMutableDictionary alloc] init];
  m_heartRateArray = [[NSMutableArray alloc] init];
  checkLeiJiNum = 0;
  //huitaike
  return self;
}


#pragma mark - BLE center delegate methods
- (BOOL) isLECapableHardware
{
    NSString * state = nil;
    switch ([_bleMgr state])
    {
        case CBCentralManagerStateUnsupported:
            state = @"The platform/hardware doesn't support Bluetooth Low Energy.";
            break;
        case CBCentralManagerStateUnauthorized:
            state = @"The app is not authorized to use Bluetooth Low Energy.";
            break;
        case CBCentralManagerStatePoweredOff:
            state = @"Bluetooth is currently powered off.";
            break;
        case CBCentralManagerStatePoweredOn:
            return TRUE;
        case CBCentralManagerStateUnknown:
        default:
            return FALSE;
            
    }
    
    //NSLog(@"Central manager state: %@", state);
    
    /*[self cancelScanSheet:nil];
     NSAlert *alert = [[[NSAlert alloc] init] autorelease];
     [alert setMessageText:state];
     [alert addButtonWithTitle:NSLocalizedString(@"OK", nil)];
     [alert setIcon:[[[NSImage alloc] initWithContentsOfFile:@"AppIcon"] autorelease]];
     [alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:nil contextInfo:nil];*/
  return FALSE;
}

//bluetooth start
- (void) startMeas:(NSString*)sBleUUID
{
  _bStopMeas = NO;
  _bReConnPedo = NO;
  //dispatch_async(dispatch_get_main_queue(), ^{
  _bConnYunmai = NO;
  _bConnNuyu = NO;
  //_sBlePerName = @"";
  
  _sBleUuid = sBleUUID;
  _bAutoConnect = YES;
    
  if(!_bIsSuptBLe) {
    if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleDiscoverFailed)]) {
      [_bleDelegate bleDiscoverFailed];
    }
    return;
  }
  [self stopMeas];
  
  [self getConnectedPeripherals];
  if(_nDevTypeIdx == 0 && hrConntMonitors.count > 0) {
    if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleMgrDiscover:)]) {
      for(CBPeripheral *connectedPeripheral in hrConntMonitors) {
        NSDictionary *options = nil;
        if([connectedPeripheral.name hasPrefix:@"HW"])
          options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnNotificationKey];
        else
          options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey];
        //[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnNotificationKey];
        [_bleMgr connectPeripheral:connectedPeripheral options:options];
        return;
      }
    }
  }
  
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  if(sBleUUID == nil) {
    NSArray  *uuidArray = nil;
    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
    //NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnNotificationKey];
    [_bleMgr scanForPeripheralsWithServices:uuidArray options:options];
  }
  else {
    //NSDictionary *options = @{ CBCentralManagerScanOptionAllowDuplicatesKey: @NO };
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
    [_bleMgr scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:sBleUUID]] options:options];
  }
  });
  
  _measTimer = [NSTimer scheduledTimerWithTimeInterval:9.00 target:self selector:@selector(onMeasTimer) userInfo:nil repeats:NO];
  
  //});
}

- (void) startScan:(NSString*)sBleUUID
{
  //_sBlePerName = @"";
  if(_bJustScanDev)
    return;
  _sBleUuid = sBleUUID;
  [hrConntMonitors removeAllObjects];
  
  if(!_bIsSuptBLe) {
    _bIsSuptBLe = [self isLECapableHardware];
    return;
  }
  _sBleUuid = sBleUUID;
  
  [self getConnectedPeripherals];
  if(_nDevTypeIdx == 0 && hrConntMonitors.count > 0) {
    if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleMgrDiscover:)]) {
      for(CBPeripheral *connectedPeripheral in hrConntMonitors) {
        [_bleDelegate bleMgrDiscover:connectedPeripheral];
        return;
      }
    }
  }
  /*[hrConntMonitors removeAllObjects];
  if(_pBleDevPer != nil) {
    if(![hrConntMonitors containsObject:_pBleDevPer])
      [hrConntMonitors addObject:_pBleDevPer];
  }*/
       
  //dispatch_async(dispatch_get_main_queue(), ^{
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    _bAutoConnect = NO;
    _measTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(onMeasTimer) userInfo:nil repeats:NO];
    //NSDictionary *options = @{ CBCentralManagerScanOptionAllowDuplicatesKey: @NO };//[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],CBCentralManagerScanOptionAllowDuplicatesKey, nil];
    
    if(sBleUUID == nil) {
      NSDictionary *options = @{ CBCentralManagerScanOptionAllowDuplicatesKey: @NO };
      [_bleMgr scanForPeripheralsWithServices:nil options:options];
    }
    else {
      NSDictionary *options = @{ CBCentralManagerScanOptionAllowDuplicatesKey: @NO };
      [_bleMgr scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:sBleUUID]] options:options];
    }
  });

  _bJustScanDev = YES;
}

- (void) stopMeas
{
  //_bleDelegate = nil;
  _bStopMeas = YES;
  //dispatch_async(dispatch_get_main_queue(), ^{
    if(_measTimer != nil) {
        [_measTimer invalidate];
        _measTimer = nil;
    }
    
    if(_pBleDevPer != nil) {
        [_bleMgr cancelPeripheralConnection:_pBleDevPer];
        _pBleDevPer = nil;
        _bConnBleDev = NO;
    }
  //});
}

- (void) stopScan
{
  //dispatch_async(dispatch_get_main_queue(), ^{
    if(!_bIsSuptBLe)
        return;
    /*if(_measTimer != nil) {
        [_measTimer invalidate];
        _measTimer = nil;
    }*/
    [_bleMgr stopScan];
    
    //[self _stopProgressView];
  //});
}

- (void)getConnectedPeripherals {
  //NSLog(@"getConnectedPeripherals");
  if(_nDevTypeIdx == 0) {
    NSArray *connectedPeripherals = [_bleMgr retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:@"180D"]]];
    for (CBPeripheral *connectedPeripheral in connectedPeripherals) {
      //NSLog(@"Connected Peripheral: %@",connectedPeripheral.name);
      if([self isHrmDevice:connectedPeripheral.name]) {
        BOOL bExists = [hrConntMonitors containsObject:connectedPeripheral];
        if(!bExists) {
          [hrConntMonitors addObject:connectedPeripheral];
        }
      }
      //[hrConntMonitors addObject:connectedPeripheral];
    }
  }

  if (_sBleUuid != nil) {
    //NSLog(@"Retrieving Connected Peripherals ...");
    NSArray *connectedPeripherals = [_bleMgr retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:_sBleUuid]]];
    //NSLog(@"Connected Peripherals with filter: %lu",(unsigned long)connectedPeripherals.count);
    for (CBPeripheral *connectedPeripheral in connectedPeripherals) {
      //NSLog(@"Connected Peripheral: %@",connectedPeripheral.name);
      [hrConntMonitors addObject:connectedPeripheral];
    }
  }
  else {
    NSString * const dfuServiceUUIDString = @"00001530-1212-EFDE-1523-785FEABCD123";
    NSString * const ANCSServiceUUIDString = @"7905F431-B5CE-4E99-A40F-4B1E122D00D0";
    
    CBUUID *dfuServiceUUID = [CBUUID UUIDWithString:dfuServiceUUIDString];
    CBUUID *ancsServiceUUID = [CBUUID UUIDWithString:ANCSServiceUUIDString];
    NSArray *connectedPeripherals = [_bleMgr retrieveConnectedPeripheralsWithServices:@[dfuServiceUUID, ancsServiceUUID]];
    //NSLog(@"Connected Peripherals without filter: %lu",(unsigned long)connectedPeripherals.count);
    for (CBPeripheral *connectedPeripheral in connectedPeripherals) {
      //NSLog(@"Connected Peripheral: %@",connectedPeripheral.name);
      [hrConntMonitors addObject:connectedPeripheral];

    }
  }
}

- (void) centralManagerDidUpdateState:(CBCentralManager *)central
{
   //[self getConnectedPeripherals];
  _bIsSuptBLe = [self isLECapableHardware];
  AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  pApp.m_bSupportBle = _bIsSuptBLe;

  
    /*if(!_bIsSuptBLe) {
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleDiscoverFailed)]) {
            [_bleDelegate bleDiscoverFailed];
        }
    }*/
    
    if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleSupport:)]) {
        [_bleDelegate bleSupport:_bIsSuptBLe];
    }
    //_btnStart.enabled = _bIsSuptBLe;
  if(!_bIsSuptBLe) {
    if(_bleDelegate  && [_bleDelegate respondsToSelector:@selector(bleUserClosed)])
      [_bleDelegate bleUserClosed];
    _bConnBleDev = NO;
  }
}

/*- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary<NSString *,id> *)dict
{
  int n = 1;
}

- (void) retrieveConnectedPeripheralsWithServices:(NSArray *)peripheralUUIDs
{
  int m = 3;
}*/

- (BOOL) IsMatchedPairDev:(NSString*) sDevUuId
{
  //return YES;
  
  BOOL bOK = [_sCurtSelUuid isEqualToString:sDevUuId];
  return bOK;
}

/*
 Invoked when the central discovers blood pressure gague peripheral or other dev while scanning.
 */
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)aPeripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
  NSString* sName = aPeripheral.name;
  if([sName hasPrefix:@"PE"] && ![sName hasPrefix:@"PE806-"] )
    return;
  
  BOOL bHwDev = [sName hasPrefix:@"HW"];
  BOOL bYunMai = [sName isEqualToString:@"YUNMAI-JY0002"] || [sName hasPrefix:@"ACCURO-FL301"];
  BOOL bNuyuScale = [sName isEqualToString:@"HjT"] || [sName isEqualToString:@"HNY200"] || (sName.length == 0);
  if(_nDevTypeIdx == 3) {
    float fSignal = RSSI.floatValue;
    if(fSignal < -80 || (!bYunMai && ! bNuyuScale))
      return;
  }
  
  //dispatch_async(dispatch_get_main_queue(), ^{
  if(aPeripheral == nil || aPeripheral.name == nil)
    return;
  
  
  //NSUInteger nCount = advertisementData.count;
  /*NSArray* pAdvArray = advertisementData.allKeys;
  for(NSInteger i=0; i<nCount; i++) {
    NSString* sVal = [pAdvArray keyval:i];
  }*/
  //NSLog(@"Scan key Count : %ld", (long)nCount);
  //for (NSString *key in advertisementData) {
    //NSLog(@"Scan key: %@ value: %@", key, advertisementData[key]);
  //}
  
  //NSString* sUuidStr = aPeripheral.UUID.string;
  //CFTypeID cfTypeId = [aPeripheral.i CFUUIDGetTypeID]
  
  //NSLog(@"peripheral.services %@", aPeripheral.UUID);
  
  
  if(_nDevTypeIdx == 0 && [_sBleUuid isEqualToString:@"180D"]) {
    if(aPeripheral.state != CBPeripheralStateConnected) { //&& !_bLoadStoreDevice
      BOOL bExists = [hrConntMonitors containsObject:aPeripheral];
      if(!bExists) {
        [hrConntMonitors addObject:aPeripheral];
      }
      //[self loadScanSaverDevices:aPeripheral.identifier.UUIDString];
      if(!_bAutoConnect && _bleDelegate && [_bleDelegate respondsToSelector:@selector(bleMgrDiscover:)]) {
        [_bleDelegate bleMgrDiscover:aPeripheral];
      }
    }
   
    /*if(_bAutoConnect) {
      [self stopScan];
      [_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                                                 forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
      [self stopScan];
      return;
    }*/
  }
  
  //BOOL bSyncDevs = [sName hasPrefix:@"PE"] || [sName hasPrefix:@"OTbeat-"] || [sName hasPrefix:@"HW"] || [self isMemroyHrm4:sName];
  BOOL bSyncDevs = NO;
  if(_nDevTypeIdx == 0 || sName != nil) {
    _bHrateDev = [self isHrmDevice:sName];
    if(bHwDev)
      bSyncDevs = NO;
    else
      bSyncDevs = [self isMemroyHrm4:sName];
  }
  else if(_nDevTypeIdx == 2) {
    bSyncDevs = [sName hasPrefix:@"PE"];
  }
  if(_nDevTypeIdx == 0 && !bSyncDevs && !_bHrateDev)
     return;
  
  BOOL bMatchUuid = [self IsMatchedPairDev:aPeripheral.identifier.UUIDString];
  if(!_bAutoConnect)
    _pBleDevPer = aPeripheral;
  else if(bSyncDevs && !bMatchUuid)
    return;
    
  BOOL bExists = [hrConntMonitors containsObject:aPeripheral];
  if(!bExists) {
    [hrConntMonitors addObject:aPeripheral];
  }
    
  BOOL bConn = _sConnBleName == nil;
  if((bConn || _nDevTypeIdx == 0) && _bAutoConnect && bMatchUuid) {
    _pBleDevPer = aPeripheral;
    [self stopScan];
      
    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey];//CBConnectPeripheralOptionNotifyOnNotificationKey];
    [_bleMgr connectPeripheral:_pBleDevPer options:options];
      //[_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
    return;
  }
  else if(!bSyncDevs) {
    if(_bAutoConnect) {
      if(sName == nil)
        return;
         
      _pBleDevPer = aPeripheral;
      if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(didDiscoverPerServices:bleMgr:)]) {
        [_bleDelegate didDiscoverPerServices:aPeripheral bleMgr:_bleMgr]; //bldp handle
      }
      else {
        BOOL bBpDev = [sName isEqual:@"Dual-SPP"] || [sName isEqualToString:@"Bluetooth BP"] || [sName isEqualToString:@"Electronic Scale"]
          ||[sName isEqualToString:@"HjT"] || [sName isEqualToString:@"HNY200"] || [sName isEqualToString:@"BOLUTEK"];
        BOOL bBracelet = [sName isEqualToString:@"HW382A"] || [sName isEqualToString:@"HW652"];
        BOOL bStepMonitor = [sName isEqualToString:@"COOBIT"];
        //BOOL bBpDev = [aPeripheral.identifier isEqual:[CBUUID UUIDWithString:@"FFF1"]] || [aPeripheral.identifier isEqual:[CBUUID UUIDWithString:@"2A51"]];
          
        if(_nDevTypeIdx != 3 && bNuyuScale)
          return;
          
        if(_nDevTypeIdx == 3) {
          if(bNuyuScale) {
            [self stopScan];
            [_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                  forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
            [self stopScan];
            return;
          }
          else {
            if(bYunMai && bConn)
              return;
          }
        }
          
        if(bBpDev || bBracelet || bYunMai || bStepMonitor) {
          //if(!bConn && !bNuyuScale)
          if(!bConn) {
            NSArray *listItems = [_sConnBleName componentsSeparatedByString:@"-"];
            NSInteger nCount = listItems.count;
            if( nCount > 1) {
              for(NSUInteger i=0; i<nCount; i++) {
                NSString* sItemName = listItems[i];
                NSRange rng = [sName rangeOfString:sItemName];
                if(rng.location != NSNotFound) {
                  [self stopScan];
                  [_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                      forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
                  [self stopScan];
                  return;
                }
              }
            }
            else {
              NSRange rng = [_sConnBleName rangeOfString:sName];
              if(rng.location != NSNotFound) {
                [self stopScan];
                [_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                      forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
                [self stopScan];
                return;
              }
            }
              
          }
      
          if(bConn && _nDevTypeIdx == 3) {
            [self stopScan];
            [_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
            [self stopScan];
          }
        }
        if(bBracelet)
          _bWriteBraceletVal = NO;
      }
    }
        //[hrConntMonitors addObject:aPeripheral];
  }
    
  if(hrConntMonitors.count > 0) {
    //if(_peripheral == nil || (!_bLoadStoreDevice && [self isLECapableHardware])) {
    if(aPeripheral.state != CBPeripheralStateConnected) { //&& !_bLoadStoreDevice
            //[self loadScanSaverDevices:aPeripheral.identifier.UUIDString];
      if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleMgrDiscover:)]) {
        [_bleDelegate bleMgrDiscover:aPeripheral];
      }
    }
  }
  else {
    //if(_peripheral == nil || (!_bLoadStoreDevice && [self isLECapableHardware])) {
    if(_pBleDevPer.state != CBPeripheralStateConnected) { //&& !_bLoadStoreDevice
      //[self loadScanSaverDevices:aPeripheral.identifier.UUIDString];
      if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleMgrDiscover:)]) {
        [_bleDelegate bleMgrDiscover:aPeripheral];
                
      }
    }
  }
  //});
}

/*
 Invoked when the central manager retrieves the list of known peripherals.
 Automatically connect to first known peripheral
 */
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
{
    //if(_bLoadStoreDevice)
    //return;
    //NSLog(@"Retrieved peripheral: %u - %@", (int)[peripherals count], peripherals);
    NSUInteger nCount = hrConntMonitors.count;
    if(nCount > 1 && _arSelBleDev == nil) {
        if(!_bAutoConnect)
            [self stopScan];
        if(_pBleDevPer) {
            [_bleMgr cancelPeripheralConnection:_pBleDevPer];
            //_peripheral = nil;
        }
        return;
    }
    /* If there are any known devices, automatically connect to it.*/
    //NSUInteger nCount = peripherals.count;
    if([peripherals count] > 0/* && autoConnect*/) {
        //[indicatorButton setHidden:FALSE];
        //[progressIndicator setHidden:FALSE];
        //[progressIndicator startAnimation:self];
        _pBleDevPer = [peripherals objectAtIndex:0];
        //[_pBleHrateSvr retain];
        [_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                        forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
        //_bLoadStoreDevice = YES;
    }
    //else {
    //[self openScanSheet:nil];
    //}
}

/*
 Invoked whenever a connection is succesfully created with the peripheral.
 Discover available services on the peripheral
 */
- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)aPeripheral
{
  _bAlreadySnedHrmData = NO;
  //dispatch_async(dispatch_get_main_queue(), ^{
    [aPeripheral setDelegate:self];
    [aPeripheral discoverServices:nil];
    _pBleDevPer = aPeripheral;
    
    if (![hrConntMonitors containsObject:aPeripheral])
      [hrConntMonitors addObject:aPeripheral];
  
    
    NSString* sUuid = aPeripheral.identifier.UUIDString;
    _sBlePerName = aPeripheral.name;
    if ([self.delegate respondsToSelector:@selector(getDevice:)]) {
        [self.delegate getDevice:_sBlePerName];
    }
    if(_bleDelegate) {
      if([_bleDelegate respondsToSelector:@selector(bleDevConnected)])
        [_bleDelegate bleDevConnected];
        
      if([_bleDelegate respondsToSelector:@selector(bleDevConnected:)])
        [_bleDelegate bleDevConnected:sUuid];
    }
  
    [self stopScan];
    _bRcvBLeData = NO;
    _bConnBleDev = YES;
    _bBatteryNotify = NO;
  
  //debug
  //AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  //_bConnSocketSvr = YES;
  //[pApp resetHostConn];
  //});
}

/*
 Invoked whenever an existing connection with the peripheral is torn down.
 Reset local variables
 */
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)aPeripheral error:(NSError *)error
{
  _bConnBleDev = NO;

  //dispatch_async(dispatch_get_main_queue(), ^{
    if(_pBleDevPer != nil) {
        [_bleMgr cancelPeripheralConnection:_pBleDevPer];
        _pBleDevPer = nil;
    }
    //[self stopMeas];
    //[self stopScan];
    
   NSString* sBleName = aPeripheral.name;
   BOOL bSyncHrDev = [sBleName hasPrefix:@"OT"]|| [sBleName hasPrefix:@"AC"];
   if(bSyncHrDev) {
     if(_bleDelegate  && [_bleDelegate respondsToSelector:@selector(bleDisconnected)])
      [_bleDelegate bleDisconnected];
   }
    else {
      if(_bleDelegate  && [_bleDelegate respondsToSelector:@selector(bleDisconnected)])
        [_bleDelegate bleDisconnected];
  }
    //if([_sBleUuid isEqualToString:@"180D"])
        //[self startMeas:@"180D"];
  //});
  
  if(_nDevTypeIdx == 2) {
    _pPedoService = nil;
  }
  
}

/*
 Invoked whenever the central manager fails to create a connection with the peripheral.
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)aPeripheral error:(NSError *)error
{
  _bConnBleDev = NO;
  //dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"Fail to connect to peripheral: %@ with error = %@", aPeripheral, [error localizedDescription]);
    //[connectButton setTitle:@"Connect"];
    if( _pBleDevPer != nil && _pBleDevPer == aPeripheral)
    {
        [_pBleDevPer setDelegate:nil];
        //[_pBleHrateSvr release];
        _pBleDevPer = nil;
    }
    //_lblState.text = [NSString stringWithFormat: @"%@ %s", [aPeripheral name], "Fail to connect"];
  //});
}

- (void) centralManager:(CBCentralManager *)central didFailToRetrievePeripheralForUUID:(CFUUIDRef)UUID error:(NSError *)error
{
	/* Nuke from plist. */
	//[self removeSavedDevice:UUID];
}

#pragma mark - CBPeripheral delegate methods
/*
 Invoked upon completion of a -[discoverServices:] request.
 Discover available characteristics on interested services
 */
- (void) peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError *)error
{
  //HW
  /*if (!error) {
    NSLog(@"services discovered %lu",(unsigned long)[aPeripheral.services count] );
    for (CBService *hrService in aPeripheral.services) {
      NSLog(@"service discovered: %@",hrService.UUID);
      if ([hrService.UUID isEqual:HR_Service_UUID]) {
        NSLog(@"HR service found");
        [aPeripheral discoverCharacteristics:nil forService:hrService];
      }
      else if ([hrService.UUID isEqual:Battery_Service_UUID]) {
        NSLog(@"Battery service found");
        [aPeripheral discoverCharacteristics:nil forService:hrService];
      }
      // code to discover DFU Service
      //else if ([hrService.UUID isEqual:dfuService_UUID]) {
        //NSLog(@"DFU Service is found");
      //}
      
    }
  } else {
    NSLog(@"error in discovering services on device: %@",aPeripheral.name);
  }*/
  
  //HW end
  
  //NSString* sUuid = aPeripheral.identifier.UUIDString;
  //NSLog(@"services discovered %lu",(unsigned long)[aPeripheral.services count] );
  
  for (CBService *aService in aPeripheral.services) {
    //if([aService.UUID isEqual:[CBUUID UUIDWithString:@"FD00"]])
      //continue;
    //NSLog(@"Service found with UUID: %@", aService.UUID);
      
    NSString* sBleName = aService.peripheral.name;
    NSString* sUuidStr = aService.UUID.UUIDString;
        
    BOOL bHwDev = [sBleName hasPrefix:@"HW"];
    BOOL bHrDev = [aService.UUID isEqual:[CBUUID UUIDWithString:@"180D"]] || [sUuidStr hasPrefix:@"180F"] || [sBleName hasPrefix:@"Smart"] || [sBleName hasPrefix:@"OTbeat"] || [sBleName hasPrefix:@"PE806-"];
    BOOL bBpDev = [aService.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]];
    BOOL bPedoDev = NO;//[sBleName hasPrefix:@"PE"];
    BOOL bYunMai = [sBleName hasPrefix:@"ACCURO-FL301"] || [sBleName hasPrefix:@"YUNMAI"];
        
    //BOOL bSyncDev = [sBleName hasPrefix:@"OT"]|| [sBleName hasPrefix:@"AC"] || bBlDev || bPedoDev;
    //BOOL bSyncDev =[sBleName hasPrefix:@"OTbeat-"];
    //if([sBleName hasPrefix:@"HRM"] || [sBleName hasPrefix:@"Smart"] || ([sBleName hasPrefix:@"OTbeat"] && !bSyncDev) || [sBleName hasPrefix:@"heart rate "]) {
    BOOL bSyncDev = [self isMemroyHrm4:sBleName] || bPedoDev;
    if(!bSyncDev) {
      _bSyncDevData = NO;
      bSyncDev = NO;
      if(_bleDelegate  && [_bleDelegate respondsToSelector:@selector(bleDevNoSyncFunc)])
        [_bleDelegate bleDevNoSyncFunc];
      //if([sBleName hasPrefix:@"HW"]) {
        //int n = 3;
        //[aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FC20"]] forService:aService];
      //}
    }
        
    if(bSyncDev) {
      if((_nDevTypeIdx == 0 && _bSyncDevData) || (_nDevTypeIdx == 2)) {
        [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FC20"],
                                               [CBUUID UUIDWithString:@"FC21"],
                                               [CBUUID UUIDWithString:@"FC22"]] forService:aService];
      }
            
      if (bHrDev) {
        if([sUuidStr hasPrefix:@"180D"]) {
          if(_bSyncDevData) {
            _pBleDevPer = aPeripheral;
            _pHrateService = aService;
          }
          else {
            //_pHrateService = nil;
            if([aPeripheral.name hasPrefix:@"Smart"] || [aPeripheral.name hasPrefix:@"OT"])
              _pHrateService = aService;
            else
              _pHrateService = nil;
            [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"2A37"]] forService:aService];
          }
        }
        else if([sUuidStr hasPrefix:@"180F"]/* && !_bSyncDevData*/) {
          [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"2A19"], [CBUUID UUIDWithString:@"FC20"]] forService:aService];
        }
        else if([sUuidStr hasPrefix:@"FC22"]) {
          _pPedoService = aService;
        }
      }
      //[self stopScan];
    }
    else if(bHwDev) {
      _bSyncDevData = [self isMemroyHrm4:aPeripheral.name];
      _pHrateService = aService;
      //[aPeripheral discoverCharacteristics:nil forService:aService];
      
      if (!error) {
        //NSLog(@"services discovered %lu",(unsigned long)[aPeripheral.services count]);
        for (CBService *hrService in aPeripheral.services) {
          NSLog(@"service discovered: %@",hrService.UUID);
          if ([hrService.UUID isEqual:HR_Service_UUID]) {
            //NSLog(@"HR service found");
            [_pBleDevPer discoverCharacteristics:nil forService:hrService];
          }
          else if ([hrService.UUID isEqual:Battery_Service_UUID]) {
            //NSLog(@"Battery service found");
            [_pBleDevPer discoverCharacteristics:nil forService:hrService];
          }
          // code to discover DFU Service
          //else if ([hrService.UUID isEqual:dfuService_UUID]) {
            //NSLog(@"DFU Service is found");
          //}
          
        }
      } else {
        //NSLog(@"error in discovering services on device: %@",aPeripheral.name);
      }
    }
    else if (bHrDev) {
      //_bSyncDevData = ![aPeripheral.name hasPrefix:@"Smart"] && ![aPeripheral.name hasPrefix:@"OTbeat"];
      //if(_bSyncDevData)
        //_bSyncDevData = ![aPeripheral.name hasPrefix:@"OTbeat-"];
      _bSyncDevData = [self isMemroyHrm4:aPeripheral.name];
      _pHrateService = aService;
      [aPeripheral discoverCharacteristics:nil forService:aService];
    }
    else if (bBpDev) {
      [aPeripheral discoverCharacteristics:nil forService:aService];
    }
    else if([aService.UUID isEqual:[CBUUID UUIDWithString:@"180F"]]) {
      //lblMsg.text = @"battery";
      [aPeripheral discoverCharacteristics:nil forService:aService];
    }
    else {
      if ([aService.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]] || [sBleName isEqualToString:@"Electronic Scale"]) {
        [aPeripheral discoverCharacteristics:nil forService:aService];
      }
      else if ([sBleName isEqualToString:@"HNY200"]) {
        [aPeripheral discoverCharacteristics:nil forService:aService];
      }
      else if ([sBleName isEqualToString:@"HjT"] || [sBleName isEqualToString:@"HNY200"] || [sBleName isEqualToString:@"BOLUTEK"] || [aService.UUID isEqual:[CBUUID UUIDWithString:@"FFE0"]] || bYunMai) {
        if(bYunMai) { // new Accuro Ble svale
          //[aPeripheral discoverCharacteristics:nil forService:aService];
          [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FFE4"],[CBUUID UUIDWithString:@"FFE5"],[CBUUID UUIDWithString:@"FFE9"]] forService:aService];
          
        }
        else {
          [aPeripheral discoverCharacteristics:nil forService:aService];
        }
      }
      else if([sUuidStr isEqualToString:@"FFE5"]) {
        [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FFE9"]] forService:aService];
      }
    }
  }
  //[self stopScan];
}

/*
 Invoked upon completion of a -[discoverCharacteristics:forService:] request.
 Perform appropriate operations on interested characteristics
 */
- (void) peripheral:(CBPeripheral *)aPeripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
  
  BOOL bBldDevFound = NO;
  //NSString* sBleName = aPeripheral.name;
  //BOOL bNuyu = [aPeripheral.name hasPrefix:@"HNY200"];
    
    /*for (CBCharacteristic *characteristic in service.characteristics) {
        NSLog(@"Discovered characteristic %@", characteristic);
    }*/
    
    if(!_bSyncDevCharFound && [service.UUID isEqual:[CBUUID UUIDWithString:@"FC00"]]) { //bracelet or HW
      for (CBCharacteristic *aChar in service.characteristics) {
        //HW start
        if ([service.UUID isEqual:HR_Service_UUID]) {
          for (CBCharacteristic *characteristic in service.characteristics)
          {
            if ([characteristic.UUID isEqual:HR_Measurement_Characteristic_UUID]) {
              NSLog(@"HR Measurement characteritsic is found");
              [_pBleDevPer setNotifyValue:YES forCharacteristic:characteristic ];
            }
            else if ([characteristic.UUID isEqual:HR_Location_Characteristic_UUID]) {
              NSLog(@"HR Position characteristic is found");
              [_pBleDevPer readValueForCharacteristic:characteristic];
            }
          }
        }
        else if ([service.UUID isEqual:Battery_Service_UUID]) {
          
          for (CBCharacteristic *characteristic in service.characteristics)
          {
            if ([characteristic.UUID isEqual:Battery_Level_Characteristic_UUID]) {
              NSLog(@"Battery Level characteristic is found");
              [_pBleDevPer readValueForCharacteristic:characteristic];
            }
          }
        }
        //HW end
        else if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]]) {//fc20
          _pBleDevChar = aChar;
          _pBleDevPer = aPeripheral;
          if(_pBleMhrChar == nil) {
            if(_nDevTypeIdx == 2) {
              [_pBleDevPer setNotifyValue:_bSyncDevData forCharacteristic:aChar];
            }
            else {
              [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
            }
            _pBleMhrChar = aChar;
          }
        }
        else if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC22"]]) {
          _pBlePedoChar = aChar;
          _pBleDevPer = aPeripheral;
          _pPedoService = service;
          if(_nDevTypeIdx == 2)
            [_pBleDevPer setNotifyValue:!_bSyncDevData forCharacteristic:aChar];
          else
            [_pBleDevPer setNotifyValue:_bHrateDev forCharacteristic:aChar];
        }
        else if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC21"]]) {
          //hui tai ke
          [m_characteristicsArray addObject:aChar];
          //hui tai ke
          
          _pBleSyncChar = aChar;
          //if(_nDevTypeIdx == 2)
            //[_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
        }
        //NSString *manufacturerName = [[NSString alloc] initWithData:aChar.value encoding:NSUTF8StringEncoding];
        //NSLog(@"manufacure name = %@ ", manufacturerName);
      }
      _bSyncDevCharFound = YES;
    }
    else if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]]) {
        for (CBCharacteristic *aChar in service.characteristics) {
            
            if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF4"]]) {
                 [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
            }
            else if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF1"]]) {
                bBldDevFound = YES;
                [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar]; //for BldMeas
                //[self sendDataToBleDev:aChar];//send data to scale
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToBleDev:)]) {
                    [_bleDelegate sendDataToBleDev:aChar];
                }
            }
             else if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF2"]]) { //write
                  _pBleDevChar = aChar;
             }
        }
    }
    else  if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFE0"]]) {
        for (CBCharacteristic *aChar in service.characteristics) {
            if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]]) {
                [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
                //NSLog(@"Found a BLE Electronic Scale Measurement Characteristic");
                if(_bleDelegate&& [_bleDelegate respondsToSelector:@selector(sendDataToBleDev:)])
                    [_bleDelegate sendDataToBleDev:aChar];
            }
            else if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE4"]]) { //yunmai accuro scale read
                [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
                //[aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FFE5"]] forService:service];
            }
            else if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE9"]]) { //yunmai accuro scale write
              _pBleDevPer = aPeripheral;
              [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
              if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToYunmaiBleDev:)])
                [_bleDelegate sendDataToYunmaiBleDev:aChar];
              _pYunmaiChar = aChar;
            }
        }
    }
    else  if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFE5"]]) { //yumai oth service
         _pBleDevPer = aPeripheral;
        aPeripheral.delegate = self;
        for (CBCharacteristic *aChar in service.characteristics) {
          if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE9"]]) { //yunmai accuro scale write
            [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
              if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToYunmaiBleDev:)])
                [_bleDelegate sendDataToYunmaiBleDev:aChar];
            _pYunmaiChar = aChar;
          }
           
        }
    }
    /*else if(bNuyu) {
      //[service setNotifyValue:YES forCharacteristic:aChar];
      if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToBleDev:)]) {
        for (CBCharacteristic *aChar in service.characteristics) {
          //NSString* sUuid = aChar.UUID.UUIDString;
          if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]]) { //yunmai accuro scale write
            [_bleDelegate sendDataToBleDev: aChar];
          }
          
        }
      }
    }*/
    
    //bld meas, write to peripheral
    BOOL bBpDev = [service.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]] || [service.UUID isEqual:[CBUUID UUIDWithString:@"1810"]];
    if (!bBldDevFound && bBpDev) {
        for (CBCharacteristic *aChar in service.characteristics) {
            bBpDev = [aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF2"]];
            if(bBpDev) {
                _pBleDevChar = aChar;
                _bConnBleDev = YES;
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToBleDev:)]) {
                    [_bleDelegate sendDataToBleDev:aChar];
                }
                return;
            }
        }
    }
    
    if ([service.UUID isEqual:[CBUUID UUIDWithString:@"180D"]] && !_bSyncDevData) {
       _pHrateService = service;
        //NSLog(@"service UUID:%@", service.UUID);
        for (CBCharacteristic *aChar in service.characteristics) {
            //if(!_bSyncDevData)
                //_pBleDevPer = aPeripheral;
            // Set notification on heart rate measurement
            if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"2A37"]])
            {
              _pBleDevChar = aChar;
              //_pHrateService = service;
              //_pBleDevPer.delegate = self;
              if(_pBleDevPer != nil && aChar != nil) {
                [_pBleDevPer setNotifyValue:!_bSyncDevData forCharacteristic:aChar];
                //NSLog(@"Found a Heart Rate Measurement Characteristic");
              }
            }
            
            //sync data
            if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]]) {
              if(_pBleMhrChar == nil) {
                [_pBleDevPer setNotifyValue:YES forCharacteristic:aChar];
                _pBleMhrChar = aChar;
              }
            }

            //NSLog(@"service UUID:%@", aChar.UUID);
        }
    }
    
    if ([service.UUID isEqual:[CBUUID UUIDWithString:@"180A"]]) {
        for (CBCharacteristic *aChar in service.characteristics) {
            /* Read manufacturer name */
            if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"2A29"]]) {
                [aPeripheral readValueForCharacteristic:aChar];
                //NSLog(@"Found a Device Manufacturer Name Characteristic");
            }
          //test
          //CBCharacteristicProperties prop = aChar.properties;
          //test
        }
    }
    
    //battery lever
    //NSString* sUuidStr = service.UUID.UUIDString;
    if([service.UUID isEqual:[CBUUID UUIDWithString:@"180F"]]) {
        /*for (CBCharacteristic *characteristic in service.characteristics) {
            //NSLog(@"discovered characteristic %@", characteristic.UUID);
            if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A19"]]) {
              //[aPeripheral setNotifyValue:NO forCharacteristic:characteristic];
              [aPeripheral readValueForCharacteristic:characteristic];
                
            }
        }*/
      
      for (CBCharacteristic *characteristic in service.characteristics)
      {
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A19"]]) {
          _pBleDevChar = characteristic;
          NSLog(@"Battery Level characteristic is found");
          [_pBleDevPer readValueForCharacteristic:characteristic];
          //[_pBleDevPer setNotifyValue:NO forCharacteristic:_pBleDevChar];
        }
      }
    }
  
  if(_bReConnPedo && _pPedoService) {
    [self enablePedoDevMeas];
  }
    
}


/*
 Invoked upon completion of a -[readValueForCharacteristic:] request or on the reception of a notification/indication.
 */
- (double) getBleWgtData:(NSData*)data fat:(float*) fFat wat:(float*)fWat wgt:(short*)nWgt wUnit:(short*)nUn fatwatInc:(BOOL*)bFatWat hgt:(float*)fHgt
{
    uint8_t bWgth, bWgtl;
    const uint8_t *reportData = [data bytes];
    uint8_t bStart = reportData[0];
    //if(bStart == 0xfd)
    //return 0.0;
    
    *bFatWat = NO;
    float dFatVal = 0.0f, dWatVal = 0.0f;
    if(bStart == 0xCf) {
        *fHgt = reportData[3] / 100.0;
        
        bWgth = reportData[4];
        bWgtl = reportData[5];
        
        uint8_t bFath = reportData[6];
        uint8_t bFatl = reportData[7];
        dFatVal = ((bFath << 8) + bFatl) / 10.0;
        
        uint8_t bWath = reportData[12];
        uint8_t bWatl = reportData[13];
        dWatVal = ((bWath << 8) + bWatl) / 10.0;
        
        if(dFatVal == 0 && dWatVal == 0)
            *bFatWat = NO;
        else
            *bFatWat = YES;
    }
    else {
        bWgth = reportData[2];
        bWgtl = reportData[3];
        //glass ble scale
        if(bWgtl == 0 && bWgth == 0) {
            bWgth = reportData[4];
            bWgtl = reportData[5];
        }
    }
    
    short nWgtVal = ((bWgth << 8) + bWgtl);
    //float fWgtVal = _nLastWgtVal / 10.0;
    double dWgtVal = nWgtVal / 10.0;
    
    *nWgt = nWgtVal;
    *nUn = 1; //1: kg, 2: lb
    
    *fFat = dFatVal;
    *fWat = dWatVal;
    
    return dWgtVal;
}

-(NSString *)getUTCFormateDate:(NSDate *)localDate
{
    //NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
    NSTimeZone *timeZone = [NSTimeZone localTimeZone];
    [_dtFormat setTimeZone:timeZone];
    [_dtFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    //[_dtFormat setDateFormat:@"MM"];
    //int month = [[_dtFormat stringFromDate:[NSDate date]] intValue];
    NSString *dateString = [_dtFormat stringFromDate:localDate];
    //[_dtFormat release];
    return dateString;
}

- (void) recvBraceLetData:(const uint8_t *)rcvData len:(NSUInteger)nDataLen char:(CBCharacteristic*)bleChar
{
    /*if(nDataLen == 6) {
        NSString* sData = [NSString stringWithFormat:@"UTC Length: %li-> %@", (long)nDataLen, characteristic.value.description];
        [_bleDelegate recvedBleOthData:sData];
    }*/
    
    uint8_t _nBraceletIdx = (rcvData[0] & 0xf0) >> 4;
    uint8_t _nBraceletCmd = rcvData[0] & 0x0f;
    if(! _bWriteBraceletVal && nDataLen == 17 && _nBraceletCmd == 0x01) {

        float fWgt = ((rcvData[7] << 8) + rcvData[8]) / 10.0;
        Byte nAge = rcvData[9];
        Byte nHgt = rcvData[10];
        Byte nSex = rcvData[12];
        [_bleDelegate recvedBleOthData:[NSString stringWithFormat:@"wgt:%.1f kg, Age:%i, Hgt:%i cm Sex: %@", fWgt, nAge, nHgt, ((nSex==0)?@"Female":@"Male")]];
        
        [NSThread sleepForTimeInterval:0.5];
        if(_pBleDevPer != nil && _pBleDevChar != nil) {
            uint8_t val[4] = {0xE0, 0x00, 0x00, 0xE0};
            val[1] = _nBraceletIdx;
            val[3] += _nBraceletIdx;
            NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
            [_pBleDevPer writeValue:valData forCharacteristic:_pBleDevChar type:CBCharacteristicWriteWithoutResponse];
            //[_pBleDevPer writeValue:valData forCharacteristic:bleChar type:CBCharacteristicWriteWithoutResponse];
            
            _bWriteBraceletVal = YES;
        }
        
    }
    else if(nDataLen == 6) {
        NSString* sData = [NSString stringWithFormat:@"%li bytes: %02X %02X %02X %02X %02X %02X", (long)nDataLen, rcvData[0], rcvData[1], rcvData[2], rcvData[3], rcvData[4], rcvData[5]];
        [_bleDelegate recvedBleOthData:sData];
        if(_nBraceletCmd == 0x0 ) {
            uint8_t val[4] = {0xE0, 0x00, 0x01, 0xE1};
            //val[1] = _nBraceletIdx;
            //val[3] += _nBraceletIdx;
            NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
            [self sendDataToBleDev:_pBleDevChar data:valData type:CBCharacteristicWriteWithResponse];
        }
        
    }
    else if(nDataLen == 15) { //fitness info
        int nSteps = (rcvData[5] >> 16) + (rcvData[6] >> 8) + rcvData[7];
        int nDists = (rcvData[8] >> 16) + (rcvData[9] >> 8) + rcvData[10];
        int nCalor =  (rcvData[11] >> 16) + (rcvData[12] >> 8) + rcvData[13];
        NSString* sInfo = [NSString stringWithFormat:@"steps:%i, Dists:%i, Calo:%i", nSteps, nDists, nCalor];
        [_bleDelegate recvedBleOthData:sInfo];
        
        uint8_t val[4] = {0xE0, 0x02, 0x00, 0xE2};
        //val[1] = _nBraceletIdx;
        //val[3] += _nBraceletIdx;
        NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
        [self sendDataToBleDev:_pBleDevChar data:valData type:CBCharacteristicWriteWithResponse];
        
    }
    else if(nDataLen == 20) {
        NSString* sInfo = @"data package leng 20, beging details";
        [_bleDelegate recvedBleOthData:sInfo];
        
    }
    else if(nDataLen == 4) {
        Byte nIdx = (rcvData[0] & 0xf0) >> 4;
        Byte nCom = rcvData[0] & 0x0f;
        BOOL bEnd = rcvData[1] == 0x03;
        Byte nPackLen = rcvData[2];
        
        NSString* sEnd = @"";
        NSString* sInfo = [NSString stringWithFormat:@"Recv package(4): idx:%i, com:%i", nIdx, nCom];
        if(bEnd) {
            sEnd = [NSString stringWithFormat:@". End len: %i", nPackLen];
        }
        
        NSMutableString* sInfos = [NSMutableString stringWithFormat:sInfo, sEnd];
        [_bleDelegate recvedBleOthData:sInfos];
        
    }
    else {
        //NSString* sInfo = [NSString stringWithFormat: @"other data received: %ld", (long)nDataLen];
        //[_bleDelegate recvedBleOthData:sInfo];
        
        NSString* sData = [NSString stringWithFormat:@"UTC Length: %li-> %@", (long)nDataLen, bleChar.value.description];
        [_bleDelegate recvedBleOthData:sData];
    }
}

/***************************************************************************
 * 方法名称：getResultData
 * 功能描述：解析出心率数据
 * 输入参数：
 * 返回数据：
 ***************************************************************************/
- (NSDictionary *)getResultData:(NSString *)resultString
{
  NSMutableDictionary *resultDic = [[NSMutableDictionary alloc] init];
  
  int j=0;
  Byte bytes[20];
  
  for(int i=0;i<[resultString length];i++)
  {
    int int_ch; //// 两位16进制数转化后的10进制数
    
    unichar hex_char1 = [resultString characterAtIndex:i]; ////两位16进制数中的第一位(高位*16)
    int int_ch1;
    if(hex_char1 >= '0' && hex_char1 <='9')
      int_ch1 = (hex_char1-48)*16; //// 0 的Ascll - 48
    else if(hex_char1 >= 'A' && hex_char1 <='F')
      int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
    else
      int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97
    i++;
    
    unichar hex_char2 = [resultString characterAtIndex:i]; ///两位16进制数中的第二位(低位)
    int int_ch2;
    if(hex_char2 >= '0' && hex_char2 <='9')
      int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
    else if(hex_char2 >= 'A' && hex_char2 <='F')
      int_ch2 = hex_char2-55; //// A 的Ascll - 65
    else
      int_ch2 = hex_char2-87; //// a 的Ascll - 97
    
    int_ch = int_ch1+int_ch2;
    //        NSLog(@"int_ch=%d",int_ch);
    bytes[j] = int_ch; ///将转化后的数放入Byte数组里
    j++;
  }
  
  int c1 = bytes[1]&0xFF;
  NSString *resultNum = [NSString stringWithFormat:@"%d",c1];
  
  [resultDic setObject:resultNum forKey:@"RateNum"];
  [resultDic setObject:@"0" forKey:@"RateMark"];
  
  return resultDic;
}

- (NSDictionary *)get10Data:(NSString *)myString
{
  if (myString.length < 4)
  {
    return nil;
  }
  
  int markNum = [[[myString substringFromIndex:1] substringToIndex:1] intValue];
  
  if ([[[myString substringFromIndex:1] substringToIndex:1] isEqualToString:@"a"] || [[[myString substringFromIndex:1] substringToIndex:1] isEqualToString:@"A"])
  {
    markNum = 10;
  }
  
  int markLongNum = [[[myString substringFromIndex:3] substringToIndex:1] intValue];
  
  NSMutableDictionary *resultDic = [[NSMutableDictionary alloc] init];
  
  int j=0;
  Byte bytes[20];
  
  for(int i=0;i<[myString length];i++)
  {
    int int_ch; //// 两位16进制数转化后的10进制数
    
    unichar hex_char1 = [myString characterAtIndex:i]; ////两位16进制数中的第一位(高位*16)
    int int_ch1;
    if(hex_char1 >= '0' && hex_char1 <='9')
      int_ch1 = (hex_char1-48)*16; //// 0 的Ascll - 48
    else if(hex_char1 >= 'A' && hex_char1 <='F')
      int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
    else
      int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97
    i++;
    
    unichar hex_char2 = [myString characterAtIndex:i]; ///两位16进制数中的第二位(低位)
    int int_ch2;
    if(hex_char2 >= '0' && hex_char2 <='9')
      int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
    else if(hex_char2 >= 'A' && hex_char2 <='F')
      int_ch2 = hex_char2-55; //// A 的Ascll - 65
    else
      int_ch2 = hex_char2-87; //// a 的Ascll - 97
    
    int_ch = int_ch1+int_ch2;
    //        NSLog(@"int_ch=%d",int_ch);
    bytes[j] = int_ch; ///将转化后的数放入Byte数组里
    j++;
  }
  
  int byteLong = (int)myString.length/2;
  int beginNum = 0;
  int endNum  = bytes[byteLong-1]&0xFF;
  for (int i = 0; i < byteLong-1; i++)
  {
    int test = bytes[i]&0xFF;
    beginNum = beginNum+test;
  }
  
  beginNum = beginNum%256;
  
  if (endNum != beginNum)
  {
    NSLog(@"*****************************检验和不一致*****************************");
    //[self disconnectBluetooth];
    [self stopMeas];
    return resultDic;
  }
  
  if (markNum == 1)
  {
    
  }
  else if (markNum == 2)
  {
    int c1 = bytes[1]&0xFF;
    int c2 = bytes[2]&0xFF;
    int c3 = bytes[3]&0xFF;
    int c4 = bytes[4]&0xFF;
    NSString *timeMinutes = [NSString stringWithFormat:@"%d",c4+(c3<<8)+(c2<<16)+(c1<<24)];
    NSDate *handTime = [NSDate dateWithTimeIntervalSince1970:[timeMinutes longLongValue]];
    NSLog(@"手环时间为：%@",handTime);
  }
  else if (markNum == 3)
  {
    
  }
  else if (markNum == 4)
  {
    
  }
  else if (markNum == 5)
  {
    
  }
  else if (markNum == 6)
  {
    return resultDic;
  }
  else if (markNum == 7)
  {
    
  }
  else if (markNum == 8)
  {
    if (markLongNum == 1)
    {
      if (m_heartRateDic.allKeys.count > 0)
      {
        NSDictionary *dic1 = [[NSDictionary alloc] initWithDictionary:m_heartRateDic];
        [m_heartRateArray addObject:dic1];
        [m_heartRateDic removeAllObjects];
      }
      
      [m_heartRateDic setObject:myString forKey:@"xinLv1"];
      checkLeiJiNum ++;
    }
    else if (markLongNum == 2)
    {
      [m_heartRateDic setObject:myString forKey:@"xinLv2"];
      checkLeiJiNum ++;
    }
    else if (markLongNum == 3)
    {
      [m_heartRateDic setObject:myString forKey:@"xinLv3"];
      checkLeiJiNum ++;
    }
    else if (markLongNum == 4)
    {
      [m_heartRateDic setObject:myString forKey:@"xinLv4"];
      checkLeiJiNum ++;
    }
    else if (markLongNum == 5)
    {
      int c2 = bytes[2]&0xFF;
      
      if (checkLeiJiNum != c2)
      {
        checkLeiJiNum = 0;
        [m_heartRateDic removeAllObjects];
        return resultDic;
      }
      else
      {
        NSDictionary *dic1 = [[NSDictionary alloc] initWithDictionary:m_heartRateDic];
        [m_heartRateArray addObject:dic1];
        [m_heartRateDic removeAllObjects];
        checkLeiJiNum = 0;
      }
    }
  }
  else if (markNum == 9)
  {
    
  }
  else if (markNum == 10)
  {
    
  }
  
  return resultDic;
}

- (void)HandHrateData:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
  if (error)
  {
    NSLog(@"didUpdateValueForCharacteristic Is Error %@",error);
    return;
  }
  NSLog(@"UUID is %@ result is %@",characteristic.UUID, characteristic.value);
  NSString *hexString  = [NSString stringWithFormat:@"%@",characteristic.value];
  hexString = [hexString stringByReplacingOccurrencesOfString:@" " withString:@""];
  hexString = [hexString stringByReplacingOccurrencesOfString:@"<" withString:@""];
  hexString = [hexString stringByReplacingOccurrencesOfString:@">" withString:@""];
  
  if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2a37"]])
  {
    NSMutableDictionary *dataDic= [[NSMutableDictionary alloc] initWithDictionary:[self getResultData:hexString]];
    [[NSNotificationCenter defaultCenter] postNotificationName:HEARTRATENUMBER object:dataDic];
    return;
  }
  
  if (hexString.length > 4) {
    int markNum = [[[hexString substringFromIndex:1] substringToIndex:1] intValue];
    
    if ([[[hexString substringFromIndex:1] substringToIndex:1] isEqualToString:@"a"] || [[[hexString substringFromIndex:1] substringToIndex:1] isEqualToString:@"A"])
    {
      markNum = 10;
    }
    
    NSString *writeStr = [hexString substringToIndex:2];
    //NSString* sTemp = [[hexString substringFromIndex:3] substringToIndex:1];
    int markLongNum = [[[hexString substringFromIndex:3] substringToIndex:1] intValue];
    int writeNum = [m_handIdea getResultData:writeStr andMark:@"0"];
    NSMutableDictionary *nowDic = [[NSMutableDictionary alloc] initWithDictionary:[self get10Data:hexString]];
    [[HandBlueValue selfAlloc] handBluetoothValue:characteristic.value];
    
    if (markNum == 1)
    {
      NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getUserInfoHand:writeNum andNowInfo:nowDic]];
      for (CBCharacteristic *charac in m_characteristicsArray)
      {
        if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
        {
          NSLog(@"write data in %@",writeData);
          [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
        }
      }
    }
    else if (markNum == 2)
    {
      NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getTimeHand:writeNum andNowInfo:nowDic]];
      for (CBCharacteristic *charac in m_characteristicsArray)
      {
        if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
        {
          NSLog(@"write data in %@",writeData);
          [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
        }
      }
    }
    else if (markNum == 3)
    {
      NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getAllHand:writeNum]];
      for (CBCharacteristic *charac in m_characteristicsArray)
      {
        if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
        {
          NSLog(@"write data in %@",writeData);
          [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
        }
      }
    }
    else if (markNum == 4)
    {
      if (markLongNum == 3)
      {
        NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getAllHand:writeNum]];
        for (CBCharacteristic *charac in m_characteristicsArray)
        {
          if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
          {
            [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
          }
        }
      }
    }
    else if (markNum == 5)
    {
      if (markLongNum == 3)
      {
        NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getAllHand:writeNum]];
        for (CBCharacteristic *charac in m_characteristicsArray)
        {
          if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
          {
            [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
          }
        }
      }
    }
    else if (markNum == 7)
    {
      NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getSetInfoHand:writeNum andNowInfo:nowDic]];
      for (CBCharacteristic *charac in m_characteristicsArray)
      {
        if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
        {
          [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
        }
      }
    }
    else if (markNum == 8)
    {
      if (markLongNum == 5)
      {
        NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getAllHand:writeNum]];
        for (CBCharacteristic *charac in m_characteristicsArray)
        {
          if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
          {
            [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
          }
        }
      }
    }
    else if (markNum == 9)
    {
      if (markLongNum == 3)
      {
        NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getAllHand:writeNum]];
        for (CBCharacteristic *charac in m_characteristicsArray)
        {
          if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
          {
            [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
          }
        }
      }
    }
    else if (markNum == 10)
    {
      NSData *writeData = [[NSData alloc] initWithData:[m_handIdea getAllHand:writeNum]];
      for (CBCharacteristic *charac in m_characteristicsArray)
      {
        if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
        {
          [peripheral writeValue:writeData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];
        }
      }
    }
#pragma mark －－－－－－返回蓝牙数据到界面－－－－－－
    else if (markNum == 6)
    {
      [peripheral setNotifyValue:NO forCharacteristic:characteristic];
      //NSString* sUuid = characteristic.UUID.UUIDString;
      
      /* 处理心率数据 */
      NSMutableArray *heartRateData = [[NSMutableArray alloc] initWithArray:[[HandBlueValue selfAlloc] endBluetoothValue]];
      [[NSNotificationCenter defaultCenter] postNotificationName:HEARTRATENUMBERHISTORY object:heartRateData];
    }
    else
    {
      return;
    }
    
    /*if((rcvData[0] & 0x0f) == 0x08) {
      NSString* sRcvMsg = @"\n";
      //if((rcvData[0] & 0x0f) == 0x08)
      //sRcvMsg = [sRcvMsg stringByAppendingFormat:@"\n"];
      
      //sRcvMsg = [sRcvMsg stringByAppendingFormat:@"%02X ", rcvData[0]];
      for(int i = 0; i<nDataLen; i++ ) {
        sRcvMsg = [sRcvMsg stringByAppendingFormat:@"%02X ", rcvData[i]];
      }
      if(rcvData[1] == 0x05)
        sRcvMsg = [sRcvMsg stringByAppendingFormat:@"\n"];
      
      
      NSLog(@"HRM Data length: %ld\n data pack: %@, ", (long)nDataLen, sRcvMsg);
    }*/
  }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
  //NSString* sUuid = characteristic.UUID.UUIDString;
  if (error) {
    NSLog(@"Error changing notification state: %@", error.localizedDescription);
  }
  
  // Notification has started
  //NSUInteger nDataLen = characteristic.value.length;
  //const uint8_t *rcvData = [characteristic.value bytes];
  //if (characteristic.isNotifying) {
    //BOOL bBroad = characteristic.isBroadcasted;
    //NSLog(@"Notification began on %@", characteristic);
  //}
}

-(float) calBodyFatRate:(float)fRes wgt:(float)fWgtKg
{
  if(_fBodyHgt == 0)
    return 0.0;
  
  float fFat = (abs(_nBodyYear - 30) + (4750 + fRes) * fWgtKg * 8.4) / (_fBodyHgt * _fBodyHgt);
  fFat = 90 * (_bBodyMale?6410:6490) / (11554 - fFat);
  return fFat;
}

- (void) peripheral:(CBPeripheral *)aPeripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
  //dispatch_async(dispatch_get_main_queue(), ^{
  //NSLog(@"UUID: %@", characteristic.UUID);
  NSString* sBleName = aPeripheral.name;//@"";
  //NSString* sCharUuid = characteristic.UUID.UUIDString;
  /*for (CBService *aService in aPeripheral.services) {
    sBleName = aService.peripheral.name;
  }*/
  //if(sBleName.length == 0)
    //return;
  NSData* pData = characteristic.value;
  NSUInteger nDataLen = pData.length;
  const uint8_t *rcvData = [pData bytes];
  
  NSString* sUuid = [characteristic.UUID UUIDString];
  //_pBleSyncChar = nil;
  for (CBCharacteristic *charac in m_characteristicsArray)
  {
    if ([charac.UUID isEqual:[CBUUID UUIDWithString:@"fc21"]])
    {
      /*uint8_t d0 = rcvData[0];
      uint8_t nIdx = d0 >> 4;
      uint8_t val[4] = {0xe0, nIdx, 0x00, 0x00};
      val[3] = (uint8_t)(0xe0 + nIdx);
      NSData* valData = [NSData dataWithBytes:(void*)val length:sizeof(val)];
      
      [aPeripheral writeValue:valData forCharacteristic:charac type:CBCharacteristicWriteWithoutResponse];*/
      _pBleDevPer = aPeripheral;
      _pBleSyncChar = charac;
    }
  }

  if([sUuid isEqualToString:@"FC21"]) {
    _pBleDevPer = aPeripheral;
    _pBleSyncChar = characteristic;
  }

  BOOL bHwatch = [sBleName hasPrefix:@"HW"];
  BOOL bBracelet = [sUuid isEqualToString:@"FC20"] && !bHwatch;
  if(!bBracelet)
    bBracelet = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FC00"]];
  BOOL bYunMai = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE4"]] && ([sBleName isEqualToString:@"YUNMAI-JY0002"] || [sBleName hasPrefix:@"ACCURO-FL301"]);
  BOOL bBleScale = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF4"]];
  if(!bBleScale)
    bBleScale = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]];
  BOOL bHrDev = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A37"]] || [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"180D"]];
  if(!bHrDev)
    bHrDev = [sBleName hasPrefix:@"OT"] || [sBleName hasPrefix:@"AC"] || [sBleName hasSuffix:@"HRM"] || [sBleName hasPrefix:@"HW"] || [sUuid isEqualToString:@"FC20"] || [sBleName hasPrefix:@"PE806-"];
  BOOL bBpDev = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF1"]] || [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A51"]];
  BOOL bPedoDev = [sBleName hasPrefix:@"PE"] && ![sBleName hasPrefix:@"PE806-"];
  //if(bHrDev && !_bSyncDevData) {
    //bPedoDev = NO;
  //}
  
  if(bYunMai)
    bHrDev = NO;
  
  if(sBleName.length == 0 && !bHrDev)
    [self sendDebugData:nil isRead:YES uuid:nil];
  else
    [self sendDebugData:pData isRead:YES uuid:nil]; //characteristic.UUID]; //characteristic.value isRead:YES];
  
  if((rcvData[0] & 0x0f) == 0x08) {
    //short n0 = rcvData[0];
    short n1 = rcvData[1];
    if (n1 == 0x01) {
      bBracelet = YES;
    }
    bBracelet = NO;
  }
    
  //battery level
  if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A19"]]) {
    //NSLog(@"Found Notify Characteristic %@", characteristic);
    //NSLog(@"value:%@",characteristic.value);
    const uint8_t *reportData = [characteristic.value bytes];
    uint8_t val = reportData[0];
    if (!_bBatteryNotify && _bleDelegate && [_bleDelegate respondsToSelector:@selector(updateBatteryLevel:)]) {
      [_bleDelegate updateBatteryLevel:val];
    }
    if((_nDevTypeIdx == 0) || _nDevTypeIdx == 2) {
      if((_pBleDevChar != nil && !_bSyncDevData)/* || (_pBleMhrChar != nil && _bSyncDevData)*/) {
        if (!_bBatteryNotify) {
          // If battery level notifications are available, enable them
          if (([characteristic properties] & CBCharacteristicPropertyNotify) > 0) {
            _pBleBatLvlChar = characteristic;
            _bBatteryNotify = YES; // mark that we have enabled notifications
            // Enable notification on data characteristic
            if(_pBleMhrChar == nil)
              [_pBleDevPer setNotifyValue:YES forCharacteristic:characteristic];
          }
        }
      }
    }
  }
  else if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FC21"]]) {
    
  }
    
  if (bHrDev) {
    //huitaike
    //[self HandHrateData:aPeripheral didUpdateValueForCharacteristic:characteristic error:error];
    //return;
    //huitaike
    
    if( (characteristic.value)  || !error ) {
      if(_pBleBatLvlChar != nil)
        [_pBleDevPer setNotifyValue:NO forCharacteristic:_pBleBatLvlChar];

      if(_bSyncDevData) {
        if([sUuid isEqualToString:@"FC20"] || [sUuid isEqualToString:@"fc20"]) {
          if((rcvData[0] & 0x0f) == 0x06) {
            [aPeripheral setNotifyValue:NO forCharacteristic:characteristic];
          }
          if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleDevSyncData:len:char:)]) {
            //[_bleDelegate recvedBleDevSyncData: rcvData len:nDataLen char:characteristic];
            [_bleDelegate recvedBleDevSyncData: rcvData len:nDataLen char:_pBleSyncChar];
            
            if(nDataLen > 0 && (rcvData[0] & 0x0f) == 0x08) {
              NSString* sRcvMsg = @"\n";
              for(int i = 0; i<nDataLen; i++ ) {
                sRcvMsg = [sRcvMsg stringByAppendingFormat:@"%02X ", rcvData[i]];
              }
              if(rcvData[1] == 0x05)
                sRcvMsg = [sRcvMsg stringByAppendingFormat:@"\n"];
                
              NSLog(@"HRM Data length: %ld\n data pack: %@, ", (long)nDataLen, sRcvMsg);
            }
          }
        }
      }
      else {
        NSData* data = pData;//characteristic.value;
        const uint8_t *reportData = [data bytes];
        uint16_t bpm = 0;
       
        if(bHwatch) {
          //if(nDataLen != 17)
            //return;
          if (![characteristic.UUID isEqual:HR_Measurement_Characteristic_UUID])
            return;
          
           //test
          if ((reportData[0] & 0x01) == 0) {
            // uint8 bpm
            bpm = reportData[1];
          }
          if (reportData[0] == 0x1B) {
            //uint16 bpm
            bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
          }
          //if(bpm == 0) {
            //bpm = reportData[1];
          //}
          NSLog(@"BPM: %d",bpm);
        }
        else {
          if ((reportData[0] & 0x01) == 0) {
            // uint8 bpm
            bpm = reportData[1];
          }
          else {
            //uint16 bpm
            bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
          }
          if(bpm == 0) {
            bpm = reportData[1];
          }
          //[_pBleDevPer setNotifyValue:YES forCharacteristic:_pBleDevChar];
        }
        if(bpm > 300)
          return;
        //self.heartRate = bpm;
        //[self showPulseData:(short)bpm];
        _bAlreadySnedHrmData = YES;
        if (!_bSyncDevData && _bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedHrateData:)]) {
          [_bleDelegate recvedHrateData:bpm];
        }
      }
            
      return;
    }
  }
  else if(bYunMai) {
    int nIdx = 6;
    float fWgtKg = 0;
    float fWgtVal = 0.0;
    short nUn = 0;
      
    if(nDataLen == 0x11) {
      if(_pYunmaiChar != nil) {
        uint8_t val[2] = {nDataLen, 0x94};
        NSData* valData = [NSData dataWithBytes:(void*)val length:sizeof(val)];
        [self sendBodyInfoToYunmaiDev:_pYunmaiChar data:valData type: CBCharacteristicWriteWithResponse];
      }
        
      nIdx = 11;
      uint8_t val[2] = {0x02, 0x94};
      NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
      [_pBleDevPer writeValue:valData forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
      
      //uint8_t nLen = rcvData[0];
      //uint8_t nCmdNo = rcvData[1];
            
      uint8_t hWgt = rcvData[nIdx];
      uint8_t lWgt = rcvData[nIdx + 1];
      short nWgt = (hWgt << 8) + lWgt;
      fWgtKg = nWgt / 100.0;
      //fWgtVal = fWgtKg * _KgcovLb;//2.20462262;
      fWgtVal = fWgtKg;
      
      //uint8_t hRes = rcvData[13];
      //uint8_t lRes = rcvData[14];
      //float fRes = ((hRes << 8) + lRes);
            
      uint8_t hFat = rcvData[15];
      uint8_t lFat = rcvData[16];
      float fFat = 0.0;
           
      if(hFat == 0 && lFat == 0) {
        fFat = 0.0;//[self calBodyFatRate:fRes wgt:fWgtKg];
      }
      else {
        fFat = ((hFat << 8) + lFat) / 100.0;
        if(fFat > 100)
          fFat = 0;
      }
            
      //water
      float fWat = (100.0 -  fFat)  * 11.0 / 16.0; //0.73;
      //musele & bone
      float fMus = (fWat * 61 + 1600 + 2 * fWgtKg - _fBodyHgt) / 100.0 - (_bBodyMale? 4: 0);
      float fBone = (float)(fFat * 103.0 + fWat *  312.0 + fWgtKg * 237.0 + _fBodyHgt * 237.0 - 154170.0 - 49.0 * _nBodyYear - 246.0 * fMus) / 10000.0f + 13.0f;
      fBone = fabsf(fBone) * _KgcovLb;;
      if(fFat == 0.0) {
        fWat = 0.0f;
        fMus = 0.0f;
        fBone = 0.0f;
      }
        
      if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedVdrBleWgtData:fat:wat:mus:bone:wUnit:fatwatInc:hgt:wgt:)]) {
        [_bleDelegate recvedVdrBleWgtData:fWgtVal fat:fFat wat:fWat mus:fMus bone:fBone wUnit:nUn fatwatInc:YES hgt:_fBodyHgt wgt:nWgt];
      }
    }
  }
  else if(bBracelet || bPedoDev) {
    if( (characteristic.value)  || !error ) {
      // Update UI with heart rate data
      if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]]) {
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleDevSyncData: len: char:)]) {
          [_bleDelegate recvedBleDevSyncData: rcvData len: nDataLen char: _pBleSyncChar];//_pBleDevChar];
          //NSString* sRcvMsg = pData.description;
          //NSLog(@"get data: %@, length: %ld", sRcvMsg, nDataLen);
        }
      }
      else if([CBUUID UUIDWithString:@"FC22"]) {
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBlePedoStepData: len:)]) {
          [_bleDelegate recvedBlePedoStepData: rcvData len: nDataLen];
          //[_pBleDevPer setNotifyValue:YES forCharacteristic:characteristic];
        }
      }
            
      /*else if (if([CBUUID UUIDWithString:@"FC22"]) {) {
        if(bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleOthData:)]) {
          //NSString* sData = [_rcvData initWithData:characteristic.value encoding:NSASCIIStringEncoding];
          //[_bleDelegate recvedBleOthData:sData];
          //[_bleDelegate recvedBleOthData:characteristic.value.description];
          [self recvBraceLetData: rcvData len: nDataLen char: characteristic];
          //[_pBleDevPer setNotifyValue:YES forCharacteristic:characteristic];
        }*/
      }
    }
    else if (bBleScale) {
      if( (characteristic.value)  || !error ) {
        // Update UI with heart rate data
        if(_bRcvBLeData)
          return;
        NSUInteger nDataLen = characteristic.value.length;
        const uint8_t *rcvData = [characteristic.value bytes];
            
        BOOL bNuyuWgt = nDataLen == 9 ||  nDataLen == 12;
        if([sBleName hasPrefix:@"HNY200"] && ! bNuyuWgt)
          return;
            
        //if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleWgtData:)]) {
        if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleWgtData:fat:wat:mus:bone:wUnit:fatwatInc:hgt:)]) {
          if(bNuyuWgt) {
            if(rcvData[0] == 'N' && rcvData[1] == 'U' && rcvData[2] == 'Y' && rcvData[3] == 'U' && rcvData[4] == 'W') {
              uint8_t bWgth = rcvData[5];
              uint8_t bWgtl = rcvData[6];
              uint8_t nUn = rcvData[7] + 1;
              //glass ble scale
              if(bWgtl == 0 && bWgth == 0) {
                return;
              }
              short nWgtVal = ((bWgth << 8) + bWgtl);
              float fWgtVal = nWgtVal / 10.0;
                        
              UInt8 nVer = 1;
              if (nDataLen > 10) {
                nVer = rcvData[10];
                  //UInt8 e = rcvData[11];
              }
              //if(nUn == 1)
              //nWgtVal *= 0.45359237;
              
              if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleWgtData:fat:wat:mus:bone:wUnit:fatwatInc:hgt:)]) {
                [_bleDelegate recvedBleWgtData:fWgtVal fat:0.0f wat:0.0f mus:0.0f bone:0.0f wUnit:nUn fatwatInc:NO hgt:0.0];
              }
            }
          }
          else {
            BOOL bIncFwat;
            short nWgtVal, nWunit;
            float fFatVal, fWatVal, fHgt;
            double dWgtVal = [self getBleWgtData:characteristic.value fat:&fFatVal wat:&fWatVal wgt:&nWgtVal wUnit:&nWunit fatwatInc:&bIncFwat hgt:&fHgt];
            [_bleDelegate recvedBleWgtData:dWgtVal fat:fFatVal wat:fWatVal mus:0.0f bone:0.0f wUnit:nWunit fatwatInc:bIncFwat hgt:fHgt];
              //[_bleDelegate recvedBleWgtData:characteristic.value];
          }
        }
            
        return;
      }
    }
    else if (bBpDev) {
      if( (characteristic.value)  || !error ) {
        NSData* data = characteristic.value;
        NSUInteger nLen = data.length;
        const uint8_t* bRcvData = [data bytes];
        BOOL bRecvPres = nLen == 7;
        if(nLen == 1 && bRcvData[0] == 0xA5 && _pBleDevPer != nil && _pBleDevChar != nil) {
          uint8_t val[6] = {0xFD, 0xFD, 0xFA, 0x05, 0x0D, 0x0A};
          NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
          [_pBleDevPer writeValue:valData forCharacteristic:_pBleDevChar type:CBCharacteristicWriteWithResponse];
        }
        else if(data.length == 5 && bRcvData[2] == 0x06) { //begin to meas
          //_bNeedStored = YES;
          _bConnBleDev = YES;
          if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(beginMeasBldPre)]) {
            [_bleDelegate beginMeasBldPre];
          }
          //_btnStart.enabled = NO;//!_btnStart.enabled;
          //_btnTurnoff.enabled = !_btnStart.enabled;
      }
      else if(bRecvPres && bRcvData[2] == 0xFB) {
        short nPresVal = bRcvData[3] * 256 + bRcvData[4];
        if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(updateBldPreVal:)]) {
          [_bleDelegate updateBldPreVal:nPresVal];
        }
        //[_vBldPres setPresVal:nPresVal];
        //_lblInfo.text = [NSString stringWithFormat:@"Measuring: %d", nPresVal];
      }
      else if(data.length == 8 && bRcvData[2] == 0xFC) { //meas end
        Byte nhPres = bRcvData[3];
        Byte nlPres = bRcvData[4];
        Byte nhRate = bRcvData[5];
                
        if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBldPreVal:lPres:hRate:)]) {
          [_bleDelegate recvedBldPreVal:nhPres lPres: nlPres hRate:nhRate];
        }
                
        //close
        uint8_t val[6] = {0xFD, 0xFD, 0xFE, 0x06, 0x0D, 0x0A};
        NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
        [_pBleDevPer writeValue:valData forCharacteristic:_pBleDevChar type:CBCharacteristicWriteWithResponse];
      }
      return;
    }
  }
  
  // Value for body sensor location received
  else if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A38"]]) {
        NSData * updatedValue = characteristic.value;
        uint8_t* dataPointer = (uint8_t*)[updatedValue bytes];
        if(dataPointer)
        {
            uint8_t location = dataPointer[0];
            NSString*  locationString;
            switch (location)
            {
                case 0:
                    locationString = @"Other";
                    break;
                case 1:
                    locationString = @"Chest";
                    break;
                case 2:
                    locationString = @"Wrist";
                    break;
                case 3:
                    locationString = @"Finger";
                    break;
                case 4:
                    locationString = @"Hand";
                    break;
                case 5:
                    locationString = @"Ear Lobe";
                    break;
                case 6:
                    locationString = @"Foot";
                    break;
                default:
                    locationString = @"Reserved";
                    break;
            }
            //NSLog(@"Body Sensor Location = %@ (%d)", locationString, location);
        }
    }
  //});
}

- (void) onMeasTimer
{
    if(_measTimer != nil) {
        [_measTimer invalidate];
        _measTimer = nil;
    }
    //rem for test and debug
    if(_pBleDevPer == nil) {
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(onBleDevDiscoverTimeOut)]) {
            [_bleDelegate onBleDevDiscoverTimeOut];
        }
    }
}

- (void) addSavedDevice:(NSString*) sUuid tryConn:(BOOL)bConn type:(short)nTypeIdx scan:(BOOL)bScan
{
  _bReConnPedo = NO;
  _bJustScanDev = NO;
  _bSyncDevCharFound = NO;
  _nDevTypeIdx = nTypeIdx;
  
  _pBleMhrChar = nil;
    //if(!_bJustScanDev)
    //if(!_bSyncDevData)
        //[self stopMeas];
  [self stopScan];
    
  _sCurtSelUuid = sUuid;
  //_sStoredPEUuid = sUuid;
    
  NSUserDefaults *userSetting = [NSUserDefaults standardUserDefaults];
  //delete old one
  if(nTypeIdx == 0) {
    [userSetting removeObjectForKey:_kStoredHMUuid];
    [userSetting setObject:nil forKey:_kStoredHMUuid];
  }
  if(nTypeIdx == 2) {
    [userSetting removeObjectForKey:_kStoredPEUuid];
    [userSetting setObject:nil forKey:_kStoredPEUuid];
  }
  [userSetting synchronize];
    
  NSArray	*storedDevices	= [[NSUserDefaults standardUserDefaults] arrayForKey:(nTypeIdx == 0)?_kStoredHMUuid: _kStoredPEUuid];
  NSMutableArray	*newDevices		= nil;
  CFStringRef		uuidString		= NULL;
    
  uuidString = (__bridge CFStringRef)sUuid;//CFUUIDCreateString(NULL, uuid);
  //if(![_sCurrUuId isEqual: (__bridge NSString *)uuidString])
  //return;
    
  if (storedDevices != nil && storedDevices.count > 0 && ![storedDevices isKindOfClass:[NSArray class]]) {
    //NSLog(@"Can't find/create an array to store the uuid");
    return;
  }
    
  if([storedDevices containsObject:(__bridge NSString*)uuidString])
    return;
    
  newDevices = [NSMutableArray arrayWithArray:storedDevices];
  if (uuidString) {
    [newDevices addObject:(__bridge NSString*)uuidString];
    //CFRelease(uuidString);
  }
    
  /* Store */
  [userSetting setObject:newDevices forKey:(nTypeIdx == 2)? _kStoredPEUuid: _kStoredHMUuid];
  [userSetting synchronize];
    
  if(bConn) {
    _bAutoConnect = YES;
    _bConnBleDev = NO;

    if(bScan) {
      _bNeedMatched = YES;
      [self startMeas:nil]; //nil//180D
      //[self startMeas:@"180D"];
    }
    else {
      [self connStoredBlePeripheral:nTypeIdx];
      [self stopScan];
    }
  }
}

- (BOOL) loadSavedDevice:(short)nTypeIdx
{
  _bJustScanDev = NO;
  _bAutoConnect = YES;
  _bSyncDevCharFound = NO;
  _pBleMhrChar = nil;
  _nDevTypeIdx = nTypeIdx;
  //if(nTypeIdx == 2)
    //return NO;
    
  _bConnBleDev = NO;
  NSString* sStoredUuid = [self getCurtStoredUuid:nTypeIdx];
  BOOL bOK = sStoredUuid != nil && sStoredUuid.length > 0;
  if(bOK) {
    //bOK = [self connStoredBlePeripheral:nTypeIdx];
    [self stopScan];
    _bSyncDevData = NO;
    if(nTypeIdx == 2) {
      //self startMeas:@"FC00"];
      bOK = [self connStoredBlePeripheral:nTypeIdx];
      _bReConnPedo = YES;
    }
    else if(nTypeIdx == 0) {
      [self startMeas:@"180D"];
      //[self addSavedDevice:sStoredUuid tryConn:YES type:nTypeIdx];
      //[self connStoredBlePeripheral:nTypeIdx];
      //[self stopScan];
      
      /*NSString* hrsServiceUUIDString = @"0000180D-0000-1000-8000-00805F9B34FB";
      CBUUID* HR_Service_UUID = [CBUUID UUIDWithString:hrsServiceUUIDString];
      NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
      [_bleMgr scanForPeripheralsWithServices:@[ HR_Service_UUID ] options:options];*/
    }
  }
  //_bLoadSavedBleDev = bOK;
  return bOK;
}

- (BOOL) isStoredUuid:(short)nTypeIdx
{
  //NSString* sStoredUuid = [self getCurtStoredUuid:nTypeIdx];
  NSArray	*storedDevices	= [[NSUserDefaults standardUserDefaults] arrayForKey:(nTypeIdx==2)?_kStoredPEUuid: _kStoredHMUuid];
  BOOL bOK = storedDevices != nil;
  if(bOK)
    bOK = storedDevices.count > 0;
  return bOK;
}

- (BOOL) connStoredBlePeripheral:(short)nTypeIdx
{
    CBPeripheral* aPeripheral = [self getCurtStorePeripheral: nTypeIdx];
    if(aPeripheral != nil) {
      _pBleDevPer = aPeripheral;
      _bAutoConnect = YES;
      _bConnBleDev = NO;
      if(![hrConntMonitors containsObject:_pBleDevPer])
        [hrConntMonitors addObject:_pBleDevPer];
      
      NSDictionary *options = nil;//CBConnectPeripheralOptionNotifyOnNotificationKey];
      if([aPeripheral.name hasPrefix:@"HW"])
        options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnNotificationKey];
      else
        options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey];
      [_bleMgr connectPeripheral:_pBleDevPer options:options];
      //[_bleMgr connectPeripheral:_pBleDevPer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                  //forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];

      [self stopScan];
    }
    
    
    return aPeripheral != nil;
}

- (CBPeripheral*) getCurtStorePeripheral:(short)nTypeIdx
{
    //NSArray* storedDevices = nil;
    NSUInteger nCount = hrConntMonitors.count;
    if(nCount == 0) {
        //storedDevices	= [[NSUserDefaults standardUserDefaults] arrayForKey:(nTypeIdx==2)?_kStoredPEUuid: _kStoredHMUuid];
        //nCount = storedDevices.count;
        return nil;
    }
    NSString* sSelUuid = [self getCurtStoredUuid: nTypeIdx];
    if(sSelUuid.length == 0)
        return nil;
    
    CBPeripheral* pCurtPeripheral = nil;
    for(NSInteger i=0; i<nCount; i++) {
        CBPeripheral* pSelPeripheral = nil;
        pSelPeripheral = [self listBleDev:i];
        NSString* sPerUuid = pSelPeripheral.identifier.UUIDString;
        if([sSelUuid isEqualToString:sPerUuid]) {
            pCurtPeripheral = pSelPeripheral;
            break;
        }
    }
    return pCurtPeripheral;// nCount > 0;
    
}

- (NSString*) getCurtStoredUuid:(short)nTypeIdx
{
    ///if(_sStoredPEUuid.length > 0)
        //return _sStoredPEUuid;
    if(_sCurtSelUuid.length > 0)
        return _sCurtSelUuid;
    
    NSArray	*storedDevices	= [[NSUserDefaults standardUserDefaults] arrayForKey:(nTypeIdx==2)?_kStoredPEUuid: _kStoredHMUuid];
    if(storedDevices == nil || storedDevices.count == 0)
       return nil;
       
    for (id deviceUUIDString in storedDevices) {
        if (![deviceUUIDString isKindOfClass:[NSString class]])
            continue;
      
        _sCurtSelUuid = deviceUUIDString;
        ///if(nTypeIdx == 2)
            //_sStoredPEUuid = deviceUUIDString;
        //if(_sStoredPEUuid.length > 0) {
            //break;
        //}
    }
    return _sCurtSelUuid;
}

- (void) sendDataToBleDev:(CBCharacteristic*)aChar data:(NSData*) valData type:(CBCharacteristicWriteType)hdType
{
  /*const uint8_t*  dBody = valData.bytes;
  _bBodyMale = dBody[8] == 1;
  _nBodyYear = (short)dBody[9];
  _fBodyHgt = (float)dBody[7];*/
    
  if(_pBleDevPer != nil && aChar != nil)
    [_pBleDevPer writeValue:valData forCharacteristic:aChar type:hdType];
  
  //[NSThread sleepForTimeInterval:0.020];
  //NSLog(@"write char point: %@", aChar);
  
  //[self sendDebugData:valData isRead:NO uuid:aChar.UUID];
}

- (BOOL) sendBodyInfoToYunmaiDev:(CBCharacteristic*)aChar data:(NSData*) valData type:(CBCharacteristicWriteType)hdType
{
  BOOL bOK = _pBleDevPer != nil && aChar != nil;
  const uint8_t*  dBody = valData.bytes;
  if(valData.length == 15) {
    _fBodyHgt = (float)dBody[7];
    _bBodyMale = dBody[8] == 1;
    _nBodyYear = (short)dBody[9];
  }
  
  if(bOK)
    [_pBleDevPer writeValue:valData forCharacteristic:aChar type:hdType];
  
  [NSThread sleepForTimeInterval:0.015]; 
  
  [self sendDebugData:valData isRead:NO uuid:aChar.UUID];
  
  return bOK;
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    NSString* sError = error.description;
    if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleOthData:)]) {
        [_bleDelegate recvedBleOthData:sError];
    }
}

#pragma mark /*-- BLE dev matcch --*/
- (NSUInteger) connBLEDevCount
{
    return hrConntMonitors.count;
}

- (NSUInteger) connBLEDevCount:(NSString*)sNamePre
{
    NSUInteger nCount = 0;
    NSUInteger n = hrConntMonitors.count;
    for(NSUInteger i=0; i<n; i++) {
        CBPeripheral* pPheral = [hrConntMonitors objectAtIndex:i];
        NSString* sBleName = pPheral.name;
        if(sBleName != nil && [sBleName hasPrefix:sNamePre])
            nCount++;
    }
    return nCount;
}

- (NSString*) getBlePerName
{
  return _sBlePerName;
}

- (BOOL) isMemroyHrmDev {
  //return YES;
  
  if(_sBlePerName.length == 0)
    return YES;
  
  BOOL bNewVer = _sBlePerName.length > 12 && ([_sBlePerName rangeOfString:@"-"].location != NSNotFound);
  return bNewVer;
}

- (BOOL) isHrmDevice:(NSString*)sBleName
{
  //return YES;
  if(_nDevTypeIdx == 0 && [_sBleUuid isEqualToString:@"180D"] /*&& [sBleName hasPrefix:@"PE806-"]*/)
    return YES;
  //else
    //return NO;
  
  BOOL bHrmDev = [self isMemroyHrm4:sBleName];
  if(!bHrmDev)
    bHrmDev = [sBleName hasPrefix:@"HRM"] || [sBleName hasPrefix:@"OT"] || [sBleName hasPrefix:@"SmartBeat"]|| [sBleName hasPrefix:@"Orangetheory"] || [sBleName hasPrefix:@"heart rate "] || [sBleName hasPrefix:@"RHYTHM+"] || [sBleName hasPrefix:@"ACCURO HRM2"] || [sBleName hasPrefix:@"DNH200-HRM"];
   if(!bHrmDev)
     bHrmDev = [sBleName rangeOfString: @"HRM"].location != NSNotFound;
  return bHrmDev;
}

- (BOOL) isMemroyHrm4:(NSString*)sBleName
{
  //return YES;
  
  if(sBleName == nil)
    return NO;
  
  if([sBleName hasPrefix:@"MIO GLOBAL-FUSE"])
    return YES;
  
  BOOL bHrm4 = [sBleName hasPrefix:@"OT"] || ([sBleName hasPrefix:@"ACCURO"] && ![sBleName hasPrefix:@"ACCURO-FL301"])|| [sBleName hasSuffix:@"HRM"] || [sBleName hasPrefix:@"Smart"] || [sBleName hasPrefix:@"OTbeat-"];// || [sBleName hasPrefix:@"ACCURO HRM4"];
  
  if([sBleName rangeOfString:@"+"].location != NSNotFound)
      bHrm4 = NO;
  else if(([sBleName hasPrefix:@"heart rate "] || [sBleName hasPrefix:@"Orangetheory HRM"] || ![sBleName hasPrefix:@"ACCURO HRM4"]))
      bHrm4 = NO;
  
  if(!bHrm4) {
    NSRange rngt = [sBleName rangeOfString:@"OTbeat-"];
    NSRange rng3 = [sBleName rangeOfString:@"HRM3"];
    NSRange rng4 = [sBleName rangeOfString:@"HRM4"];
    if(rngt.location != NSNotFound || rng3.location != NSNotFound || rng4.location != NSNotFound )
      bHrm4 = YES;
   //if([sBleName hasPrefix:@"9RUND"] || [sBleName hasPrefix:@"OTbeat-"] || [sBleName hasPrefix:@"ACCURO HRM3"] || [sBleName hasPrefix:@"ACCURO HRM4"])
      //bHrm4 = YES;
  }
  
  if(sBleName.length < 12 && [sBleName rangeOfString:@"h"].location == NSNotFound)
    bHrm4 = NO;
  
  if(!bHrm4)
    bHrm4 = [sBleName hasPrefix:@"HW"];
  
  if(!bHrm4) {
    if(_sBlePerName == nil || [_sBlePerName isEqualToString:@""])
      _sBlePerName = sBleName;
    bHrm4 = [self isTestHRMDevice];
  }
  
  return bHrm4;
}

- (void) setConnBleName:(NSString*) sBleName
{
  _sConnBleName = sBleName;
}

- (CBPeripheral*) listBleDev:(NSInteger)nIdx
{
    if(nIdx >= hrConntMonitors.count)
        return nil;
    return [hrConntMonitors objectAtIndex:nIdx];
}

- (void) retrievePeripherals:(NSArray *)peripheralUUID
{
    //[_bleMgr retrievePeripherals:peripheralUUID];
    [_bleMgr retrievePeripheralsWithIdentifiers:peripheralUUID];
    
    /*NSUUID *uuid = [[NSUUID alloc]initWithUUIDString:peripheralUUID];
     //where savedUUID is the string version of the NSUUID you've saved somewhere
     
     NSArray *peripherals = [_bleMgr retrievePeripheralsWithIdentifiers:@[uuid]];
     return peripherals;*/
}

- (void) cancelPeripheralConnection/*:(CBPeripheral *)peripheral*/
{
    [_bleMgr cancelPeripheralConnection:_pBleDevPer];
    _pBleDevPer = nil;
}

-(void) disablePedoSyncSvr
{
    if(_pBleDevPer != nil)
        [_pBleDevPer setNotifyValue:NO forCharacteristic:_pBleSyncChar];
}

- (void) enabHratNotification
{
  if(_pBleDevPer != nil) {
    if(_pHrateService != nil && !_bAlreadySnedHrmData)
      [_pBleDevPer discoverCharacteristics:@[[CBUUID UUIDWithString:@"2A37"]] forService:_pHrateService];
  }
}

- (void) enableSyncChar:(CBCharacteristic*)pChar enable:(BOOL)bEnable
{
  if(_pBleDevPer != nil) {
    if(pChar != nil)
      [_pBleDevPer setNotifyValue:bEnable forCharacteristic:pChar];
    if(!bEnable && _pHrateService != nil) {
      _bSyncDevData = NO;
      if(_pBleMhrChar != nil)
        [_pBleDevPer setNotifyValue:NO forCharacteristic:_pBleMhrChar];
      [_pBleDevPer discoverCharacteristics:@[[CBUUID UUIDWithString:@"2A37"]] forService:_pHrateService];
    }
  }
  
    /*if(_bSyncDevData) {
        if(_pBleDevPer != nil && _pBleSyncChar != nil)
            [_pBleDevPer setNotifyValue:bEnable forCharacteristic:_pBleSyncChar];//pChar;
        if(_pBleDevPer != nil && _pBleDevChar != nil)
            [_pBleDevPer setNotifyValue:!bEnable forCharacteristic:_pBleDevChar];
    }
    else {
        if(_pBleDevPer != nil && _pBleDevChar != nil)
            [_pBleDevPer setNotifyValue:bEnable forCharacteristic:_pBleDevChar];//pChar];
        if(_pBleDevPer != nil && _pBleSyncChar != nil)
            [_pBleDevPer setNotifyValue:!bEnable forCharacteristic:_pBleSyncChar];
    }*/

}

- (void) enablePedoDevMeas
{
  if(_pBleDevPer) {
    if(_pBleDevChar && _pBleDevChar.isNotifying)
      [_pBleDevPer setNotifyValue:NO forCharacteristic:_pBleDevChar];
    //if(_pBleSyncChar && _pBleSyncChar.isNotifying)
      //[_pBleDevPer setNotifyValue:NO forCharacteristic:_pBleSyncChar];
  }
  
  if(_pBlePedoChar) {
    if(!_pBlePedoChar.isNotifying) {
      _bHrateDev = NO;
      [_pBleDevPer setNotifyValue:YES forCharacteristic:_pBlePedoChar];
    }
  }
  else if(_pPedoService) {
    _bHrateDev = NO;
    [_pBleDevPer discoverCharacteristics:@[[CBUUID UUIDWithString:@"FC22"]] forService:_pPedoService];
  }
}

- (void) resetCurtSelUuid
{
  _sCurtSelUuid = @"";
}

-(void) sendDebugData:(NSData*) pData isRead:(BOOL)bRead uuid:(CBUUID*)cbUuid
{
  return;
  
  /*NSUInteger nDataLen = pData.length;
  const uint8_t *bData = [pData bytes];
  
  NSString* sData = [[NSString alloc] init];
  for(NSInteger i=0; i<nDataLen; i++) {
    sData = [sData stringByAppendingFormat:@"%02X ", bData[i]];
  }
  sData = [sData stringByAppendingString:@"\n"];
  
  NSString* sMsg = nil;
  if(bRead)
    sMsg = [NSString stringWithFormat:@"\nNotice length %i: %@",(int)nDataLen, sData];
  else
    sMsg = [NSString stringWithFormat:@"\nWrite length %i: %@",(int)nDataLen, sData];
  //sMsg = [sMsg stringByAppendingFormat:@" with uuid: %@\n", cbUuid];
  NSLog(@"%@", sMsg);
  
  if(!_bConnSocketSvr)
    return;
  
  AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  Boolean bConn = [pApp ConnScaleHost:YES IpAddr:_IP_ADDR_Deubg];
  NcitWiFiDev* ncitSock = pApp.m_ncitWiFiDev;
  if(!bConn) {
    _bConnSocketSvr = NO;
    return;
  }
    
  if(_bConnSocketSvr && pData == nil && bRead) {
    [ncitSock sendData:"NO BLE Name send\n" Alert:NO];
    return;
  }

  
  if(_bConnSocketSvr && (_nDebugDataType == 0 || _nDebugDataType == 1)) {
     [ncitSock sendData:(char*)(sMsg.UTF8String) Alert:NO];
  
     //[pApp CloseScaleHost];
   }*/
}

//-(void) sendDebugHrate:(short)nHrate time:(NSDate*)dtMeas count:(int)nIdx
- (void) sendDebugHrate:(short)nHrate dtStart:dtMeas dtEnd:dtLast count:(int)nIdx
{
  return;
  
  /*if(!_bConnSocketSvr)
     return;
  
  AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  Boolean bConn = [pApp ConnScaleHost:YES IpAddr:_IP_ADDR_Deubg];
  NcitWiFiDev* ncitSock = pApp.m_ncitWiFiDev;
  if(!bConn) {
    _bConnSocketSvr = NO;
    return;
  }
  NSString* sInitDtFmt = pApp.dtFmt.dateFormat;
  [pApp.dtFmt setDateFormat: @"yyyy-MM-dd HH:mm:ss"];
  
  if(nHrate == 0 && dtLast == nil && dtLast == nil && nIdx == 0) {
    [ncitSock sendData:"Data package not strat with 1\n" Alert:NO];
    [pApp.dtFmt setDateFormat: sInitDtFmt];
    return;
  }
  
  if(_nDebugDataType == 0 || _nDebugDataType == 2) {
   
  
    NSString* sMsg = @"";
    //if(nIdx == 1) {
      //sMsg = @"H rate:\n";
    //}
    if(nHrate > 0) {
      if((nIdx % 20) == 0)
        sMsg = [sMsg stringByAppendingFormat:@"%i\n", nHrate];
      else
        sMsg = [sMsg stringByAppendingFormat:@"%i, ", nHrate];
      [ncitSock sendData:(char*)(sMsg.UTF8String) Alert:NO];
    }
    else if(nHrate == -1) {
      if(dtLast != nil) {
        NSString* sEnd = [NSString stringWithFormat:@"\nSync Heart Rate End: %@\n", [pApp.dtFmt stringFromDate:dtLast]];
        [ncitSock sendData:(char*)(sEnd.UTF8String) Alert:NO];
      }
    }
    else if(dtMeas != nil && dtLast != nil) {
      //if(dtMeas != nil && dtLast != nil) {
      sMsg = [NSString stringWithFormat:@"\nSync Heart Rate: %@ ~ %@\n\n\n", [pApp.dtFmt stringFromDate:dtMeas], [pApp.dtFmt stringFromDate:dtLast]];
      [ncitSock sendData:(char*)(sMsg.UTF8String) Alert:NO];
    }
  
    [pApp.dtFmt setDateFormat: sInitDtFmt];
  }*/
}

- (BOOL) isTestHRMDevice
{
  if(_sBlePerName == nil)
    return NO;
  
  BOOL bTest = [_sBlePerName hasPrefix:@"OTbeat-"] && [_sBlePerName rangeOfString:@"h"].location != NSNotFound;
  if(!bTest)
    bTest = [_sBlePerName rangeOfString:@"ACCURO HRM3  0065537"].location != NSNotFound;
  return bTest;
  
}


@end
